package cn.itsource.order.service.impl;

import cn.itsource.basic.service.impl.BaseServiceImpl;
import cn.itsource.basic.utils.CodeGenerateUtils;
import cn.itsource.basic.utils.DistanceUtil;
import cn.itsource.basic.utils.Point;
import cn.itsource.order.domain.OrderAddress;
import cn.itsource.order.domain.ProductOrder;
import cn.itsource.order.domain.ProductOrderDetail;
import cn.itsource.order.service.IOrderAddressService;
import cn.itsource.order.service.IProductOrderDetailService;
import cn.itsource.order.service.IProductOrderService;
import cn.itsource.org.domain.Shop;
import cn.itsource.org.service.IShopService;
import cn.itsource.pay.contants.BusinessType;
import cn.itsource.pay.domain.PayBill;
import cn.itsource.pay.service.IPayBillService;
import cn.itsource.product.domain.Product;
import cn.itsource.product.service.IProductService;
import cn.itsource.user.domain.User;
import cn.itsource.user.domain.UserAddress;
import cn.itsource.user.service.IUserAddressService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class ProductOrderServiceImpl extends BaseServiceImpl<ProductOrder> implements IProductOrderService {

    @Autowired
    private IProductService productService;

    @Autowired
    private IUserAddressService userAddressService;

    @Autowired
    private IShopService shopService;

    @Autowired
    private IProductOrderDetailService productOrderDetailService;

    @Autowired
    private IOrderAddressService orderAddressService;

    @Autowired
    private IPayBillService payBillService;


    /*
     创建订单：
        1.根据购买的服务id 查询出对应的Product
        2.生成订单号（生成逻辑，不能重复，支持高并发）
        3.计算最后的支付时间
        4.获取当前系统的登录用户
        5.计算离用户最近的门店

     创建订单详情：
        1.把一个购买的Product 里面的数据放到 OrderProductDetail 对象里面
        2.返回创建订单的主键，放到OrderProductDetail里面


     创建订单的上门地址表：
        1.根据用户选择的地址，查询对应的UserAddress
        2.把UserAddress里面的数据拷贝到 OrderAddress里面
        3.返回创建订单的主键，放到OrderAddress里面
     -------------------------支付相关-----------------------------

     创建支付单：


     调用支付接口支付订单：
        调用支付接口


    */
    @Override
    @Transactional
    public String createOrder(HashMap<String, String> map,User user) {
        //map里面的所有数据取出来
        Long product_id =Long.valueOf(map.get("product_id"));//购买的服务id
        Integer payWay =Integer.valueOf(map.get("pay_way"));//支付方式
        Long address_id =Long.valueOf(map.get("address_id"));//上门服务的地址

        //用户购买的产品
        Product product = productService.queryById(product_id);
        //用户上门的地址
        UserAddress userAddress = userAddressService.queryById(address_id);

        //创建订单：
        ProductOrder order = createProductOrder(product,user);
        Point point = DistanceUtil.getPoint(userAddress.getFullAddress());
        List<Shop> shopList = shopService.query();
        //计算出最近的商家
        Shop shop = DistanceUtil.getNearestShop(point, shopList);
        order.setShop(shop);
        super.save(order);

        //创建订单详情
        ProductOrderDetail productOrderDetail = productToProductOrderDetail(product);
        //订单详情关联订单
        productOrderDetail.setProductOrder(order);
        productOrderDetailService.save(productOrderDetail);


        // 创建订单的上门地址表：
        OrderAddress orderAddress= userAddressToOrderAddress(userAddress);
        //设置关联信息
        orderAddress.setProductOrder(order);
        orderAddress.setOrderSn(order.getOrderSn());
        orderAddressService.save(orderAddress);
        
        //创建支付单：
        PayBill payBill =  createPaybill(order);
        payBill.setPayChannel(payWay);
        payBill.setUser(user);
        payBill.setShop(shop);
        payBill.setShopName(shop.getName());
        payBill.setOrderSn(order.getOrderSn());
        payBillService.save(payBill);

        //调用支付的接口方法 支付订单

        String payResult = payBillService.goPay(payBill, order.getOrderSn());
        return payResult;
    }

    private PayBill createPaybill(ProductOrder order) {
        PayBill payBill = new PayBill();
        payBill.setDigest(order.getDigest());
        payBill.setMoney(order.getPrice());
        payBill.setState(0);
        payBill.setLastPayTime(order.getLastPayTime());
        payBill.setCreateTime(new Date());
        payBill.setBusinessType(BusinessType.BUSINESS_PRODUCT);
        payBill.setBusinessKey(order.getId());
        return payBill;
    }

    /*
     创建订单的上门地址表：
        1.根据用户选择的地址，查询对应的UserAddress
        2.把UserAddress里面的数据拷贝到 OrderAddress里面
        3.返回创建订单的主键，放到OrderAddress里面
     */
    private OrderAddress userAddressToOrderAddress(UserAddress userAddress) {
        OrderAddress orderAddress = new OrderAddress();
        BeanUtils.copyProperties(userAddress,orderAddress);

        return orderAddress;
    }

    /*
         1.把一个购买的Product 里面的数据放到 OrderProductDetail 对象里面
        2.返回创建订单的主键，放到OrderProductDetail里面
     */
    private ProductOrderDetail productToProductOrderDetail(Product product) {
        ProductOrderDetail productOrderDetail = new ProductOrderDetail();
        //数据拷贝 按照javabean可写属性来进行拷贝
        BeanUtils.copyProperties(product,productOrderDetail);
        //设置关联的产品
        productOrderDetail.setProduct(product);
        return productOrderDetail;
    }

    /*
        1.根据购买的服务id 查询出对应的Product
        2.生成订单号（生成逻辑，不能重复，支持高并发）
        3.计算最后的支付时间
        4.获取当前系统的登录用户
        5.计算离用户最近的门店
     */
    private ProductOrder createProductOrder(Product product,User user) {
        ProductOrder productOrder = new ProductOrder();
        productOrder.setDigest("【服务订单】"+product.getName());
        productOrder.setState(0);
        productOrder.setPrice(product.getSaleprice());
        //最后的支付时间 30分钟
        productOrder.setLastPayTime(new Date(System.currentTimeMillis()+30*60*1000));
        productOrder.setProduct(product);
        //处理生成订单号问题  生成订单号 传入当前用户的id
        productOrder.setOrderSn(CodeGenerateUtils.generateOrderSn(user.getId()));
        //哪个用户下的订单
        productOrder.setUser(user);
        //计算离用户最近的门店

        return  productOrder;
    }


}
